package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.spel.ast.NullLiteral;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @author Sanmier
 * @create 2020-12-18 18:37
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper,OrderInfo> implements OrderService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    //保存订单
    @Override
    @Transactional
    public Long saveOrder(OrderInfo orderInfo) {

        //总金额、订单状态、userId、out_trade_no--第三方交易编号
        //订单描述、创建时间、过期时间、进程状态
        //总金额
        orderInfo.sumTotalAmount();
        //订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //userId
        //orderInfo.setUserId();  //用户id在控制器获取
        //out_trade_no--第三方交易编号
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + "" + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述(获取每个商品名称)
            //        StringBuilder sb = new StringBuilder();
            //        for (OrderDetail orderDetail : orderInfo.getOrderDetailList()) {
            //            //拼接字符串
            //            sb.append(orderDetail.getSkuNum());
            //        }
            //        if (sb.length()>200){
            //            //包前不包后
            //            orderInfo.setTradeBody(sb.toString().substring(0, 200));
            //        }else {
            //            orderInfo.setTradeBody(sb.toString());
            //        }
        orderInfo.setTradeBody("购买一栋别墅。。");

        //创建时间
        orderInfo.setCreateTime(new Date());
        //过期时间默认24小时
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1);
        //过期时间
        orderInfo.setExpireTime(calendar.getTime());
        //进程状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());


        //保存订单
        orderInfoMapper.insert(orderInfo);
        //保存订单明细
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();

        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }

        //返回订单Id
        return orderInfo.getId();
    }


    //生产流水号
    @Override
    public String getTradeNo(String userId) {
        //声明流水号
        String tradeNo = UUID.randomUUID().toString();
        //放入缓存
        String tradeNoKey = "tradeCode:" + userId;

        redisTemplate.opsForValue().set(tradeNoKey, tradeNo);
        //返回
        return tradeNo;
    }


    //比较流水号
    @Override
    public boolean checkTradeNo(String tradeNo, String userId) {
        //先获取缓存的
        String tradeNoKey = "tradeCode:" + userId;
        String tradeNoRedis = (String) redisTemplate.opsForValue().get(tradeNoKey);

        //比较返回结果
        return tradeNo.equals(tradeNoRedis);
    }


    //删除流水号
    @Override
    public void deleteTradeNo(String userId) {
        String tradeNoKey = "tradeCode:" + userId;
        redisTemplate.delete(tradeNoKey);

    }


    //验证库存
    @Override
    public boolean checkStock(Long skuId, Integer skuNum) {
        //远程调用
        String res = HttpClientUtil.doGet("http://localhost:9001/hasStock?skuId=" + skuId + "&num=" + skuNum);
        //判断返回结果
        return "1".equals(res);
    }


    //取消订单
    @Override
    public void execExpiredOrder(Long orderId) {

//        OrderInfo orderInfo = new OrderInfo();
//        orderInfo.setId(orderId);
//        orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
//        orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
//        orderInfoMapper.updateById(orderInfo);

        //进度状态中能获取订单状态
        updateOrderStatus(orderId,ProcessStatus.CLOSED);

        //发送一个消息关闭电商本地paymentInfo交易记录
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE, orderId);
    }


    //  更新订单状态
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
                OrderInfo orderInfo = new OrderInfo();
                orderInfo.setId(orderId);
                orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
                orderInfo.setProcessStatus(processStatus.name());
                orderInfoMapper.updateById(orderInfo);
    }



    // 根据订单Id 查询订单信息
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        //查询订单明细
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (orderInfo!=null){
            orderInfo.setOrderDetailList(orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_id", orderId)));
        }
        return orderInfo;
    }


    //根绝订单id发送消息给库存
    @Override
    public void sendOrderStatus(Long orderId) {
        //改变一下订单的状态
        updateOrderStatus(orderId, ProcessStatus.NOTIFIED_WARE);

        //先获取到发送信息的数据  由orderInfo组成
        //  需要获取订单对象
        OrderInfo orderInfo = getOrderInfo(orderId);
        //在类中定义一个方法 讲orderInfo转换成Map
        Map map = this.initWareOrder(orderInfo);
        //将map转换成Json
        String wareJson = JSON.toJSONString(map);

        //发送消息
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK, MqConst.ROUTING_WARE_STOCK,wareJson );
    }

    //在类中定义一个方法  将orderInfo转成Map
    //后面拆单时需要使用
    public Map initWareOrder(OrderInfo orderInfo){
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "2");
        map.put("wareId", orderInfo.getWareId());// 仓库Id ，减库存拆单时需要使用！
        //存储的是订单明细
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();

        //声明一个List集合来存储map
        List<Map> maps = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {
            HashMap<String, Object> detailMap = new HashMap<>();
            detailMap.put("skuId",orderDetail.getSkuId());
            detailMap.put("skuNum",orderDetail.getSkuNum());
            detailMap.put("skuName",orderDetail.getSkuName());
            maps.add(detailMap);
        }
        map.put("details",maps);
        return map;
    }


    //根绝orderId、wareSkuMap获取子订单集合
    @Override
    public List<OrderInfo> orderSplit(String orderId, String wareSkuMap) {
        /*
        1、获取原始订单
        2、将wareSkuMap变为我们能操作的对象
        3、给子订单赋值 并将子订单添加到集合中
        4、保存子订单
        5、更新原始订单的状态
         */
        List<OrderInfo> orderInfoList = new ArrayList<>();
        OrderInfo orderInfoOrigin = this.getOrderInfo(Long.parseLong(orderId));
        List<Map> mapList = JSON.parseArray(wareSkuMap, Map.class);
        if (!CollectionUtils.isEmpty(mapList)){
            for (Map map : mapList) {
                //获取仓库Id
                String wareId = (String) map.get("wareId");
                //获取仓库对应的商品id
                List<String> skuIdList = (List<String>) map.get("skuIds");

                //创建子订单
                OrderInfo subOrderInfo = new OrderInfo();
                BeanUtils.copyProperties(orderInfoOrigin, subOrderInfo);
                //设置主键为空
                subOrderInfo.setId(null);
                //设置某些字段
                subOrderInfo.setWareId(wareId);
                subOrderInfo.setParentOrderId(Long.parseLong(orderId));

                //计算价格  必须给子订单的订单明细
                //根据skuId获取子订单明细
                //先获取到原始订单明细
                List<OrderDetail> orderDetailList = orderInfoOrigin.getOrderDetailList();

                //声明一个子订单明细集合
                List<OrderDetail> orderDetails = new ArrayList<>();
                //遍历原始订单明细
                for (OrderDetail orderDetail : orderDetailList) {
                    //  找到仓库对应的skuIdList
                    for (String skuId : skuIdList){
                        //根据skuId
                        //if (orderDetail.getSkuId().compareTo(Long.parseLong(skuId))==0){
                        //
                        //}
                        if (orderDetail.getSkuId()==Long.parseLong(skuId)){
                            //将子订单明细对象放入子订单中
                            orderDetails.add(orderDetail);
                        }
                    }
                }
                subOrderInfo.setOrderDetailList(orderDetails);
                subOrderInfo.sumTotalAmount();
                //保存子订单
                this.saveOrder(subOrderInfo);

                //将子订单添加到集合中
                orderInfoList.add(subOrderInfo);
            }
        }
        //修改原始订单状态
        this.updateOrderStatus(Long.parseLong(orderId), ProcessStatus.SPLIT);

        return orderInfoList;
    }


    //更新近期订单
    @Override
    public void execExpiredOrder(Long orderId, String flag) {
        //调用方法  状态
        updateOrderStatus(orderId, ProcessStatus.CLOSED);
        if ("2".equals(flag)){
            //发送消息队列  关闭支付宝的交易记录

            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
        }
    }

}
